﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using StackExchange.Redis;

namespace Simple.Common.Cache
{
    public partial class RedisService
    {
        #region string
        ///// <summary>
        ///// 设置缓存（无失效时间）。
        ///// </summary>
        ///// <param name="key">键。</param>
        ///// <param name="value">值。</param>
        ///// <returns></returns>
        //public async Task<bool> SetAsync(string key, object value)
        //{
        //    if (value is null)
        //    {
        //        return await _database.StringSetAsync(GetKey(key), RedisValue.Null);
        //    }
        //    var type = value.GetType();

        //    if (type == typeof(string) || type.IsValueType)
        //    {
        //        return await _database.StringSetAsync(GetKey(key), value.ToString());
        //    }

        //    return await _database.StringSetAsync(GetKey(key), JsonConvert.SerializeObject(value));
        //}
        /// <summary>
        /// 设置缓存（有效期）。
        /// </summary>
        /// <param name="key">键。</param>
        /// <param name="value">值。</param>
        /// <param name="expireTimeSpan">有效期。</param>
        /// <param name="isExpire"></param>
        /// <returns></returns>
        public async Task<bool> SetAsync(string key, object value, TimeSpan? expireTimeSpan = _expireTimeSpan, bool? isExpire = false)
        {
            if (value is null)
            {
                return await _database.StringSetAsync(GetKey(key), RedisValue.Null, expireTimeSpan);
            }

            var type = value.GetType();

            if (type == typeof(string) || type.IsValueType)
            {
                return await _database.StringSetAsync(GetKey(key), value.ToString(), expireTimeSpan);
            }

            return await _database.StringSetAsync(GetKey(key), JsonConvert.SerializeObject(value), expireTimeSpan);
        }

        /// <summary>
        /// 指定键是否存在。
        /// </summary>
        /// <param name="key">键。</param>
        /// <returns></returns>
        public async Task<bool> IsExsitsAsync(string key) => await _database.KeyExistsAsync(GetKey(key));

        /// <summary>
        /// 获取字符串缓存。
        /// </summary>
        /// <param name="key">键。</param>
        /// <returns></returns>
        public async Task<string> GetAsync(string key)
        {
            var value = await _database.StringGetAsync(GetKey(key)).ConfigureAwait(false);

            return value.IsNullOrEmpty ? default : value;
        }
        /// <summary>
        /// 获取缓存（泛型）。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="key">键。</param>
        /// <returns></returns>
        public async Task<T> GetAsync<T>(string key)
        {
            var value = await _database.StringGetAsync(GetKey(key)).ConfigureAwait(false);

            if (value.IsNullOrEmpty)
            {
                return default;
            }
            var type = typeof(T);

            var valueStr = value.ToString();

            if (type == typeof(string) || type == typeof(object))
            {
                return (T)(object)valueStr;
            }

            return type.IsValueType ? (T)(object)value : JsonConvert.DeserializeObject<T>(value); ;
        }
        /// <summary>
        /// 清除指定缓存。
        /// </summary>
        /// <param name="key">键。</param>
        /// <returns></returns>
        public async Task RemoveAsync(string key) => await _database.KeyDeleteAsync(GetKey(key));
        /// <summary>
        /// 批量清除缓存。
        /// </summary>
        /// <param name="keys">键集合。</param>
        /// <returns></returns>
        public Task RemoveAsync(IEnumerable<string> keys)
        {
            if (keys is null)
            {
                throw new ArgumentNullException(nameof(keys));
            }
            var list = keys
                .Distinct()
                .ToList();

            return list.Count == 0 ? Task.CompletedTask : _database.KeyDeleteAsync(list.Select(key => new RedisKey(GetKey(key))).ToArray());
        }
        #endregion

    }
}
